﻿using log4net;
using System;
using System.Collections;
using System.Collections.Generic;
using Velocity4Net.Errors;

namespace Velocity4Net.Runtime.Parser.Node
{

    /*
     * Licensed to the Apache Software Foundation (ASF) under one
     * or more contributor license agreements.  See the NOTICE file
     * distributed with this work for additional information
     * regarding copyright ownership.  The ASF licenses this file
     * to you under the Apache License, Version 2.0 (the
     * "License"); you may not use this file except in compliance
     * with the License.  You may obtain a copy of the License at
     *
     *   http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing,
     * software distributed under the License is distributed on an
     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
     * KIND, either express or implied.  See the License for the
     * specific language governing permissions and limitations
     * under the License.
     */






    /**
     * SetExecutor that is smart about Maps. If it detects one, it does not
     * use Reflection but a cast to access the setter.
     *
     * @author <a href="mailto:henning@apache.org">Henning P. Schmiedehausen</a>
     * @version $Id: MapSetExecutor.java 1780734 2017-01-28 19:21:08Z cbrisson $
     * @since 1.5
     */
    public class MapSetExecutor
           : SetExecutor
    {
        private readonly String property;

        public MapSetExecutor(ILog log, Type clazz, String property)
        {
            this.log = log;
            this.property = property;
            discover(clazz);
        }

        protected void discover(Type clazz)
        {
            Class[] interfaces = clazz.getInterfaces();
            foreach (Class anInterface in interfaces)
            {
                if (typeof(anInterface.Equals(Map)))
            {
                    try
                    {
                        if (property != null)
                        {
                            setMethod(typeof(Dictionary).getMethod("put", typeof(Object), typeof(Object)));
                        }
                    }
                    /**
                     * pass through application level runtime exceptions
                     */
                    catch (SystemException e)
                    {
                        throw e;
                    }
                    catch (Exception e)
                    {
                        String msg = "Exception while looking for put('" + property + "') method";
                        log.Error(msg, e);
                        throw new VelocityException(msg, e);
                    }
                    break;
                }
            }
        }

        public Object execute(Object o, Object arg)
        {
            ((IDictionary)o).Add(property, arg);
            return arg;
        }
    }
}